#include "yysemaphore.h"
// std or system
#include <stdexcept>
#include <errno.h>
// app common
#include <log/logger.h>

namespace thread {



static const uint32_t kBufLen = 128;

Semaphore::Semaphore(uint32_t value):
  value_(value)
{
  MEMBER_DEBUG_LOG("[+]Semaphore::ctor");
  int sys_errno = 0;
  int err = ::sem_init( &sem_, 0, value_ );
  if ( 0 != err )
  {
    sys_errno = errno; // if -1 is returned, and errno is set to indicate the error
    char buf[kBufLen] = {0};
    snprintf(buf, kBufLen, "Error #%d on ::sem_init, errno:: %d", err, sys_errno);
    MEMBER_LOG( LOG_ERR, "%s", buf);
    throw std::runtime_error(buf);
  }
  MEMBER_DEBUG_LOG("[-]Semaphore::ctor");
}

Semaphore::~Semaphore()
{
  MEMBER_DEBUG_LOG("[+]Semaphore::dtor");
  int sys_errno = 0;
  int err = ::sem_destroy( &sem_ );
  if ( 0 != err )
  {
    sys_errno = errno; // if -1 is returned, and errno is set to indicate the error.
    MEMBER_LOG( LOG_ERR, "Error #%d on ::sem_destroy, errno: %d", err, sys_errno);
  }
  MEMBER_DEBUG_LOG("[-]Semaphore::dtor");
}

int Semaphore::Post()
{
  MEMBER_DEBUG_LOG("[+]Semaphore::Post");
  int sys_errno = 0;
  int err = sem_post( &sem_ );
  if ( err )
  {
    sys_errno = errno; // if -1 is returned, and errno is set to indicate the error.
    MEMBER_LOG( LOG_ERR, "Error #%d on ::sem_post, errno: %d", err, sys_errno);
  }
  MEMBER_DEBUG_LOG("[-]Semaphore::Post");
  return sys_errno;
}

int Semaphore::Wait()
{
  MEMBER_DEBUG_LOG("[+]Semaphore::Wait");
  int sys_errno = 0;
  int err = ::sem_wait( &sem_ );
  if ( 0 != err )
  {
    sys_errno = errno; // if -1 is returned, and errno is set to indicate the error.
    MEMBER_LOG( LOG_ERR, "Error #%d on ::sem_wait, errno: %d", err, sys_errno);
  }
  MEMBER_DEBUG_LOG("[-]Semaphore::Wait");
  return sys_errno;
}

int Semaphore::TimedWait(const struct timespec& timeout)
{
  MEMBER_DEBUG_LOG("[+]Semaphore::TimedWait");
  int sys_errno = 0;
  int err = ::sem_timedwait( &sem_, &timeout);
  if ( 0 != err )
  {
    sys_errno = errno; // if -1 is returned, and errno is set to indicate the error.
    MEMBER_LOG( LOG_ERR, "Error #%d on ::sem_timedwait, errno: %d", err, sys_errno);
  }
  MEMBER_DEBUG_LOG("[-]Semaphore::TimedWait");
  return sys_errno;
}

}

